<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace buwang\util\wechat;

use app\common\model\MemberMiniapp;
use app\common\model\WechatOpenToken;
use EasyWeChat\Factory;
use Symfony\Component\HttpFoundation\Request;
use Yurun\Util\Swoole\Guzzle\SwooleHandler;

class WechatMp
{
    /**
     * 小程序和公众号共用
     *  获取微信开放平台配置【代小程序或公众号实现业务】
     * @return \EasyWeChat\OpenPlatform\Application
     */
    public function getOpenPlatform()
    {
        $info = bw_config('wechatopen');//获取总平台开放平台的配置
        $config = [
            'app_id' => $info['app_id'],
            'secret' => $info['secret'],
            'token' => $info['token'],
            'aes_key' => $info['aes_key'],
            'log' => [
                'default' => 'dev', // 默认使用的 channel，生产环境可以改为下面的 prod
                'channels' => [
                    // 测试环境
                    'dev' => [
                        'driver' => 'single',
                        'path' => public_path().'wechat_dev.log',
                        'level' => 'debug',
                    ],
                    // 生产环境
                    'prod' => [
                        'driver' => 'daily',
                        'path' => public_path().'wechat_prod.log',
                        'level' => 'info',
                    ],
                ],
            ],
        ];
        $application = Factory::openPlatform($config);
        $request = request();
        $application['guzzle_handler'] = SwooleHandler::class;
        $application->rebind('request', new Request($request->get(), $request->post(), [], [], [], $request->server(), $request->getContent()));
        return $application;
    }

    /**
     * 获取租户应用对应的开放平台或单独的公众号easywechat操作实例
     * @param int $bw_member_app_id
     * @return \EasyWeChat\OfficialAccount\Application|false|void
     */
    public function getWechatObj(int $bw_member_app_id)
    {
        try {
            $app_info = MemberMiniapp::where(['id' => $bw_member_app_id])->find();

            return empty($app_info->miniapp->is_openapp) ? self::official($bw_member_app_id, $app_info) : self::openPlatformOfficial($bw_member_app_id, $app_info);
        } catch (\Throwable $e) {
            return false;
        }
    }

    /**
     * 微信公众号单独操作实例
     * @param int $bw_member_app_id
     * @param array $bw_member_app
     * @return \EasyWeChat\OfficialAccount\Application|false
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function official(int $bw_member_app_id = 0, $bw_member_app = [])
    {
        if ($bw_member_app_id) {
            if (empty($bw_member_app)) {
                $bw_member_app = MemberMiniapp::where(['id' => $bw_member_app_id])->field('mp_appid,mp_secret')->find();
            }
            $config = ['app_id' => $bw_member_app['mp_appid'], 'secret' => $bw_member_app['mp_secret']];
        } else {
            //获取租户端扫码登录配置信息
            $bw_member_app = bw_config('scan');
            $config = ['app_id'  => $bw_member_app['mp_id'],'secret'  => $bw_member_app['mp_secret'],'token'   => $bw_member_app['mp_token'],'aes_key' => $bw_member_app['mp_aes_key']];
        }
        if (empty($config['app_id']) || empty($config['secret'])) {
            return false;
        }
        return Factory::officialAccount($config);//公众号单独操作实例
    }

    /**
     * 微信公众号开放平台操作实例
     * @param int $bw_member_app_id
     * @param array $bw_member_app
     * @return \EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application|false
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function openPlatformOfficial(int $bw_member_app_id, $bw_member_app = [])
    {
        if (empty($bw_member_app)) {
            $bw_member_app = MemberMiniapp::where(['id' => $bw_member_app_id])->field('mp_appid')->find();
        }
        if (empty($bw_member_app['mp_appid'])) {
            return false;
        }
        $refreshToken = WechatOpenToken::refreshToken($bw_member_app_id, $bw_member_app['mp_appid']);
        if (empty($refreshToken)) {
            return false;
        }
        return self::getOpenPlatform()->officialAccount($bw_member_app['mp_appid'], $refreshToken['refreshToken']);
    }
    /**
     * 公众号前端用到的JSSDK配置
     * @param int $bw_member_app_id 租户应用id
     * @param array $jsApiList
     * @return mixed
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function jsApiList(int $bw_member_app_id, $jsApiList = [])
    {
        if (empty($jsApiList)) {
            $jsApiList = ["checkJsApi", "invokeMiniProgramAPI", "launchMiniProgram", "hideMenuItems", 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'scanQRCode', "onMenuShareTimeline", "onMenuShareAppMessage", "closeWindow", "getNetworkType", "previewImage", "onVoiceRecordEnd", "onVoicePlayEnd", 'chooseWXPay', 'chooseCard', 'openCard', 'addCard', 'openAddress', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getLocalImgData'];
        }
        $url = request()->param('url');//如果前端传url值就重新设置加密参与参数url
        $jssdkObj = self::getWechatObj($bw_member_app_id)->jssdk;
        if (isset($url)) $jssdkObj = self::getWechatObj($bw_member_app_id)->jssdk->setUrl(urldecode($url));
        return $jssdkObj->buildConfig($jsApiList, false);
    }
}